package com.joysuch.wwyt.bp.service.impl;


import com.alibaba.fastjson.JSON;
import com.joysuch.wwyt.bp.bean.inspect.BPInspectPointBean;
import com.joysuch.wwyt.bp.bean.inspect.BPInspectPointDetailBean;
import com.joysuch.wwyt.bp.bean.inspect.BPInspectPointQueryBean;
import com.joysuch.wwyt.bp.entity.inspect.BPInspectPoint;
import com.joysuch.wwyt.bp.entity.inspect.BPInspectPointDetail;
import com.joysuch.wwyt.bp.entity.inspect.BPInspectPointType;
import com.joysuch.wwyt.bp.repository.BPInspectPointDetailRepository;
import com.joysuch.wwyt.bp.repository.BPInspectPointRepository;
import com.joysuch.wwyt.bp.repository.BPInspectPointTypeRepository;
import com.joysuch.wwyt.bp.service.BPInspectPointService;
import com.joysuch.wwyt.bp.service.BpDepartService;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.enums.DeleteFlag;
import com.joysuch.wwyt.risk.repository.RiskDistrictDao;
import com.querydsl.core.types.ExpressionUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 巡检： 巡检点Service
 */

@Slf4j
@Service
@Transactional
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class BPInspectPointServiceImpl implements BPInspectPointService {

    @Autowired
    private BPInspectPointRepository inspectPointDao;

    @Autowired
    private BPInspectPointDetailRepository inspectPointDetailDao;

    @Autowired
    private BPInspectPointTypeRepository inspectPointTypeDao;

    @Autowired
    private RiskDistrictDao riskDistrictDao;

    @Autowired
    private BpDepartService bpDepartService;

    @Override
    public Page<BPInspectPoint> page(Pageable pageable, BPInspectPointQueryBean queryBean) {
        Specification<BPInspectPoint> specification = new Specification<BPInspectPoint>() {
            @Override
            public Predicate toPredicate(Root<BPInspectPoint> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Predicate predicate = criteriaBuilder.conjunction();
                predicate = criteriaBuilder.equal(root.get("deleteFlag"), DeleteFlag.EFFECTIVE.getCode());
                if(queryBean.getInspectType() != null && queryBean.getInspectType() !=0){
                    predicate = criteriaBuilder.equal(root.get("inspectType"),queryBean.getInspectType());
                }
                if(queryBean.getInspectArea() != null && queryBean.getInspectArea() !=0){
                   // predicate = criteriaBuilder.equal(root.get("inspectArea"),queryBean.getInspectArea());
                    predicate = criteriaBuilder.equal(root.get("inspectArea"),queryBean.getInspectArea());
                }
                Predicate and = criteriaBuilder.and(predicate);
                if(StringUtils.isNotBlank(queryBean.getNameOrCode())){
                    Predicate inspectName = criteriaBuilder.like(root.get("inspectName"), "%" + queryBean.getNameOrCode() + "%");
                    Expression<String> id1 = criteriaBuilder.concat(root.get("id"), "");
                    Predicate id = criteriaBuilder.like(id1,queryBean.getNameOrCode());
                    Predicate or = criteriaBuilder.or(inspectName, id);
                    return criteriaBuilder.and(and,or);
                }
                return criteriaBuilder.and(predicate);
            }
        };

        Page<BPInspectPoint> page =  inspectPointDao.findAll(specification, pageable);
        for(BPInspectPoint point: page){
          if(point == null){
              continue;
          }
          // 检查点类型名称
            Optional<BPInspectPointType> inspectType = inspectPointTypeDao.findById(point.getInspectType());
            inspectType.ifPresent(type -> point.setInspectTypeName(type.getTypeName()));

            //查询风险风区名称
            String riskDistrictName = riskDistrictDao.findNameById(point.getInspectArea());
            point.setInspectAreaName(riskDistrictName);
        }

        return page;
    }

    @Override
    public ResultBean save(BPInspectPointBean bean) {
        BPInspectPoint dbInspect = inspectPointDao.findByInspectName(bean.getInspectName());
        BPInspectPoint entity = null;
        //新增保存
        boolean isNew = true;
        if(bean.getId() == null || bean.getId() ==0){
            if(dbInspect != null){
              return  ResultBean.wrapErrorResultDefault("检查点名称已经存在。");
            }
            entity = new BPInspectPoint();
            entity.setInspectCount(0);
            //新增时类型对应的统计数量 +1
            inspectPointTypeDao.updateInspectTypeCount(bean.getInspectType(), 1);
        }else{
            if(dbInspect != null && !dbInspect.getId().equals(bean.getId())){
                return  ResultBean.wrapErrorResultDefault("检查点名称不能重复。");
            }
            isNew = false;
            entity = inspectPointDao.findById(bean.getId()).get();
            //修改时类型如果变化： 原始统计数量 -1， 新类型+1
            if(!entity.getInspectType().equals(bean.getInspectType())){
                inspectPointTypeDao.updateInspectTypeCount(entity.getInspectType(), -1);
                inspectPointTypeDao.updateInspectTypeCount(bean.getInspectType(), 1);
            }
        }

        BeanUtils.copyProperties(bean, entity);
        entity = inspectPointDao.save(entity);
        Map<Long, BPInspectPointDetail> detailMap = new HashMap<>();
        List<Long> newIdList = new ArrayList<>();
        //保存 检查点对应的设备列表详情
        if(bean.getDetails() != null){
            List<BPInspectPointDetail> entityList = new ArrayList<>();
            for(BPInspectPointDetailBean detail: bean.getDetails()){
                BPInspectPointDetail detailEntity = null;
                if(detail.getId() == null || detail.getId() == 0){
                    detailEntity = new BPInspectPointDetail();
                    detailEntity.setInspectPointId(entity.getId());
                }else{
                   detailEntity = inspectPointDetailDao.findById(detail.getId()).get();
                }
                detailEntity.setDeviceId(detail.getDeviceId());
                //保存检查项目内容列表为JSONArray 格式
                detailEntity.setInspectItem(JSON.toJSONString(detail.getInspectItem()));
                detailEntity.setInspectStandard(JSON.toJSONString(detail.getInspectStandard()));
                detailEntity.setInspectItemIds(JSON.toJSONString(detail.getInspectItemIds()));;
                detailEntity.setInspectPointId(entity.getId());
                entityList.add(detailEntity);
            }
           List<BPInspectPointDetail> saveList = inspectPointDetailDao.saveAll(entityList);
            newIdList= saveList.stream().map(BPInspectPointDetail::getId).collect(Collectors.toList());


        }
        //修改列表， 需要剔除已删除的数据
        if(!isNew){
           List<BPInspectPointDetail> details = inspectPointDetailDao.findAllByInspectPointId(bean.getId());
           List<BPInspectPointDetail> deleteList = new ArrayList<>();
           for(BPInspectPointDetail detail: details){
              if(!detailMap.containsKey(detail.getId()) && !newIdList.contains(detail.getId())){
                  deleteList.add(detail);
              }
           }
           //删除页面未保留的设备列表
           if(deleteList.size()>0){
               inspectPointDetailDao.deleteAll(deleteList);
           }
        }
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public BPInspectPointBean getById(Long id) {
        BPInspectPointBean bean = new BPInspectPointBean();
        Optional<BPInspectPoint> optionalBPInspectPoint = inspectPointDao.findById(id);
        if (optionalBPInspectPoint.isPresent()) {
            BPInspectPoint entity = optionalBPInspectPoint.get();
            BeanUtils.copyProperties(entity, bean);
            //查询风险风区名称
            String riskDistrictName = riskDistrictDao.findNameById(entity.getInspectArea());
            bean.setInspectAreaName(riskDistrictName);
            List<BPInspectPointDetailBean> details = inspectPointDetailDao.findDetails(id);
            //部门名称
            String departName = bpDepartService.findById(bean.getDepartId()).getName();
            bean.setDepartName(departName);
            bean.setDetails(details);
        }
        return bean;
    }

    @Override
    public ResultBean deleteById(Long id) {


        // 验证是否有检查点引用此类型
        Optional<BPInspectPoint> point = inspectPointDao.findById(id);
        if(point.isPresent()){
            if(point.get().getInspectCount() != null && point.get().getInspectCount() >0 ){
                return ResultBean.wrapErrorResultDefault("当前检查点已被检查计划关联，请先解除关联后再删除。");
            }
        }
        inspectPointTypeDao.updateInspectTypeCount(point.get().getInspectType(), -1);

        //删除设备列表记录
        inspectPointDetailDao.deleteBPInspectPointDetailByInspectPointId(id);
        //删除巡检点主表记录
        inspectPointDao.deleteById(id);

      return ResultBean.defaultSuccessResult();


    }
}
